<!-- src/views/video/config/index.vue -->
<template>
  <div class="config-container">
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form :model="configsQuery" ref="queryForm" :inline="true">
        <el-form-item label="配置名称" prop="name">
          <el-input v-model="configsQuery.name" placeholder="请输入配置名称" clearable />
        </el-form-item>
        <el-form-item label="配置状态" prop="status" style="width: 220px">
          <el-select v-model="configsQuery.isDefault" placeholder="请选择配置状态" clearable>
            <el-option
                v-for="item in statusOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="配置类型" prop="type" style="width: 180px">
          <el-select v-model="configsQuery.configType" placeholder="配置类型" clearable>
            <el-option label="单数字人" value="single" />
            <el-option label="多数字人" value="multiple" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">
            <el-icon><Search /></el-icon>查询
          </el-button>
          <el-button @click="resetQuery">
            <el-icon><Refresh /></el-icon>重置
          </el-button>
          <!-- 添加同步按钮 -->
          <el-button type="success" @click="handleSync" :loading="syncLoading">
            <el-icon><RefreshRight /></el-icon>同步数据
          </el-button>
          <!-- 添加最后同步时间显示 -->
          <el-tag type="info" v-if="lastSyncTime" style="margin-left: 10px;">
            最后同步时间: {{ formatDateTime(lastSyncTime.syncTime) }}
          </el-tag>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 配置列表 -->
    <el-card>
      <template #header>
        <div class="left">
          <el-button-group>
<!--            <el-button type="primary" @click="handleAdd('single')">-->
<!--              <el-icon><Plus /></el-icon>新增单数字人配置-->
<!--            </el-button>-->
            <el-button type="success" @click="handleAdd('multiple')" style="margin: 0 10px">
              <el-icon><Plus /></el-icon>新增数字人配置
            </el-button>
            <el-button type="warning" :disabled="selectedConfigs.length <= 0" @click="handleBatchDelete">
              <el-icon><Delete /></el-icon>批量删除
            </el-button>
          </el-button-group>
          <el-tag v-if="selectedConfigs.length" type="info">
            已选择 {{ selectedConfigs.length }} 项
          </el-tag>
        </div>
      </template>

      <el-table
          :data="configStore.configs"
          v-loading="configStore.loading"
          border
          @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column prop="name" label="配置名称" min-width="150" />
        <el-table-column label="配置类型" width="110">
          <template #default="scope">
            <el-tag :type="scope.row.configType === 'multiple' ? 'success' : ''">
              {{ scope.row.configType === 'multiple' ? '多数字人' : '单数字人' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="虚拟人物" min-width="180">
          <template #default="scope">
            <!-- 单数字人配置 -->
            <div v-if="scope.row.configType !== 'multiple'" class="avatar-cell">
              <el-image
                  :src="scope.row.avatar?.previewImageUrl"
                  class="avatar-preview"
                  fit="cover"
              >
                <template #error>
                  <div class="image-placeholder">
                    <el-icon><Avatar /></el-icon>
                  </div>
                </template>
              </el-image>
              <span>{{ scope.row.avatar?.avatarName }}</span>
            </div>

            <!-- 多数字人配置 -->
            <div v-else class="multi-avatar-cell">
              <el-tag type="success">{{ scope.row.avatarCount || 0 }} 个数字人</el-tag>
              <el-button link type="primary" @click="viewMultiAvatars(scope.row)">查看详情</el-button>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="语音" min-width="150">
          <template #default="scope">
            <!-- 单数字人配置 -->
            <div v-if="scope.row.configType !== 'multiple'" class="voice-cell">
              <el-icon><Microphone /></el-icon>
              <span>{{ scope.row.voice?.name }}</span>
              <el-button
                  link
                  type="primary"
                  @click="handlePreviewVoice(scope.row.voice)"
              >试听</el-button>
            </div>
            <!-- 多数字人配置 -->
            <span v-else>--</span>
          </template>
        </el-table-column>
        <el-table-column label="背景类型" width="120">
          <template #default="scope">
            <el-tag :type="getBackgroundTypeTag(scope.row.backgroundType)">
              {{ getBackgroundTypeLabel(scope.row.backgroundType) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="背景预览" width="150">
          <template #default="scope">
            <!-- 颜色背景 -->
            <div v-if="scope.row.backgroundType === 'color'" class="color-cell">
              <div
                  class="color-block"
                  :style="{ backgroundColor: scope.row.backgroundColor }"
              ></div>
              <span>{{ scope.row.backgroundColor }}</span>
            </div>

            <!-- 图片背景 -->
            <div v-else-if="scope.row.backgroundType === 'image'" class="background-preview">
              <el-image
                  :src="scope.row.backgroundUrl"
                  class="background-thumbnail"
                  fit="cover"
                  :preview-src-list="[scope.row.backgroundUrl]"
                  :initial-index="0"
                  preview-teleported
              >
                <template #error>
                  <div class="image-placeholder">
                    <el-icon><Picture /></el-icon>
                  </div>
                </template>
              </el-image>
            </div>

            <!-- 视频背景 -->
            <div v-else-if="scope.row.backgroundType === 'video'" class="background-preview">
              <div class="video-container" @click="previewVideo(scope.row.backgroundUrl)">
                <video
                    :src="scope.row.backgroundUrl"
                    class="background-thumbnail"
                    muted
                    :controls="false"
                    @mouseover="handleVideoMouseOver"
                    @mouseout="handleVideoMouseOut"
                ></video>
                <div class="video-overlay">
                  <el-icon class="video-icon"><VideoPlay /></el-icon>
                </div>
              </div>
            </div>

            <!-- 无背景 -->
            <span v-else>--</span>
          </template>
        </el-table-column>
        <el-table-column label="分辨率" width="120">
          <template #default="scope">
            {{ scope.row.width }} x {{ scope.row.height }}
          </template>
        </el-table-column>
        <el-table-column label="默认配置" width="100">
          <template #default="scope">
            <el-switch
                v-model="scope.row.isDefault"
                @change="(val) => handleSetDefault(scope.row, val)"
            />
          </template>
        </el-table-column>
        <el-table-column label="开启字幕" width="100">
          <template #default="scope">
            <el-switch
                v-model="scope.row.isCaption"
                @change="(val) => handleSetCaption(scope.row, val)"
            />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" fixed="right">
          <template #default="scope">
            <el-button
                type="primary"
                link
                @click="handleEdit(scope.row)"
            >编辑</el-button>
            <el-button
                type="danger"
                link
                @click="handleDelete(scope.row)"
                :disabled="scope.row.isDefault"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination">
        <el-pagination
            v-model:current-page="configsQuery.current"
            v-model:page-size="configsQuery.size"
            :total="configStore.total"
            :page-sizes="[10, 20, 50, 100]"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 单数字人配置编辑弹窗 -->
    <el-dialog
        v-model="configDialog.visible"
        :title="configDialog.type === 'add' ? '新增配置' : '编辑配置'"
        width="800px"
        :close-on-click-modal="false"
    >
      <el-form
          ref="configFormRef"
          :model="configForm"
          :rules="rules"
          label-width="100px"
      >
        <el-form-item label="配置名称" prop="name">
          <el-input v-model="configForm.name" placeholder="请输入配置名称" />
        </el-form-item>

        <!-- 虚拟人物选择 -->
        <el-form-item
            label="虚拟人物"
            prop="avatarId"
            :rules="[{ required: true, message: '请选择虚拟人物' }]"
        >
          <div class="select-preview">
            <div v-if="currentAvatar" class="preview-content">
              <el-image
                  style="height: 40px;width: 40px"
                  :src="currentAvatar.previewImageUrl"
                  class="preview-image"
                  fit="cover"
              >
                <template #error>
                  <div class="image-placeholder">
                    <el-icon><Avatar /></el-icon>
                  </div>
                </template>
              </el-image>
              <div class="preview-info">
                <span>{{ currentAvatar.avatarName }}</span>
                <el-space>
                  <el-tag size="small" :type="getGenderType(currentAvatar.gender)">
                    {{ getGenderLabel(currentAvatar.gender) }}
                  </el-tag>
                  <el-tag size="small" :type="'danger'">
                    {{currentAvatar.premium === true ? '高级版' : '基础版'}}
                  </el-tag>
                </el-space>
              </div>
              <div class="avatar-actions" style="text-align: center">
                <el-button
                    type="primary"
                    link
                    size="small"
                    @click="handlePreview(currentAvatar)"
                >
                  <el-icon><VideoPlay /></el-icon>预览
                </el-button>
              </div>
            </div>
            <el-button @click="showAvatarDialog = true">
              {{ currentAvatar ? '更换' : '选择' }}虚拟人物
            </el-button>
          </div>
        </el-form-item>

        <!-- 人物配置 - 新增部分 -->
        <el-form-item label="人物配置">
          <el-collapse>
            <el-collapse-item title="详细配置">
              <div class="avatar-config-form">
                <div class="config-row">
                  <span class="config-label">水平偏移 (X):</span>
                  <el-slider
                      v-model="configForm.xOffset"
                      :min="-1"
                      :max="1"
                      :step="0.05"
                      show-input
                      :format-tooltip="value => value.toFixed(2)"
                  />
                </div>
                <div class="config-row">
                  <span class="config-label">垂直偏移 (Y):</span>
                  <el-slider
                      v-model="configForm.yOffset"
                      :min="-1"
                      :max="1"
                      :step="0.05"
                      show-input
                      :format-tooltip="value => value.toFixed(2)"
                  />
                </div>
                <div class="config-row">
                  <span class="config-label">缩放比例:</span>
                  <el-slider
                      v-model="configForm.scale"
                      :min="0.1"
                      :max="2"
                      :step="0.1"
                      show-input
                      :format-tooltip="value => value.toFixed(2)"
                  />
                </div>
                <div class="avatar-config-tip">
                  <el-alert
                      type="info"
                      :closable="false"
                      show-icon
                  >
                    <template #title>配置建议</template>
                    <div>
                      <p>半身人物建议设置: X: 0.0, Y: 0.25, Scale: 1</p>
                      <p>正值向右/向上偏移，负值向左/向下偏移</p>
                      <p>详细配置请参考 <el-link href="https://docs.heygen.com/page/tools" type="primary" target="_blank">HeyGen文档</el-link></p>
                    </div>
                  </el-alert>
                </div>
              </div>
            </el-collapse-item>
          </el-collapse>
        </el-form-item>

        <!--- 角色语音选择 --->
        <el-form-item
            label="语音"
            prop="voiceId"
            :rules="[{ required: true, message: '请选择语音' }]"
        >
          <div class="select-preview">
            <div v-if="currentVoice" class="preview-content">
              <div class="preview-info">
                <span>{{ currentVoice.name }}</span>
                <div class="preview-tags">
                  <el-tag size="small" type="success">{{ getLanguageLabel(currentVoice.language) }}</el-tag>
                  <el-tag size="small" :type="getGenderType(currentVoice.gender)">
                    {{ getGenderLabel(currentVoice.gender) }}
                  </el-tag>
                </div>
              </div>
              <el-button
                  link
                  type="primary"
                  @click="handlePreviewVoice"
                  :disabled="!currentVoice.previewAudio"
              >试听</el-button>
            </div>
            <el-button @click="showVoiceDialog = true">
              {{ currentVoice ? '更换' : '选择' }}语音
            </el-button>
          </div>
        </el-form-item>

        <el-form-item label="背景类型" prop="backgroundType">
          <el-radio-group v-model="configForm.backgroundType" @change="handleBackgroundTypeChange">
            <el-radio label="color">颜色背景</el-radio>
            <el-radio label="image">图片背景</el-radio>
            <el-radio label="video">视频背景</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 颜色背景设置 -->
        <el-form-item v-if="configForm.backgroundType === 'color'" label="背景颜色" prop="backgroundColor">
          <el-color-picker v-model="configForm.backgroundColor" />
          <span class="color-value">{{ configForm.backgroundColor }}</span>
        </el-form-item>

        <!-- 图片/视频背景设置 -->
        <template v-if="configForm.backgroundType === 'image' || configForm.backgroundType === 'video'">
          <el-form-item :label="configForm.backgroundType === 'image' ? '背景图片' : '背景视频'">
            <div class="background-resource-container">
              <!-- 已选择的背景预览 -->
              <div v-if="configForm.backgroundUrl" class="preview" style="width: 200px;">
                <el-image
                    v-if="configForm.backgroundType === 'image'"
                    :src="configForm.backgroundUrl"
                    class="preview-image"
                    fit="cover"
                ></el-image>
                <video
                    v-else
                    :src="configForm.backgroundUrl"
                    class="preview-video"
                    autoplay
                    loop
                    muted
                ></video>
                <el-button
                    class="remove-btn"
                    type="danger"
                    circle
                    @click="removeBackground"
                    size="small"
                >
                  <el-icon><Delete /></el-icon>
                </el-button>
              </div>

              <!-- 操作按钮 -->
              <div class="background-actions">
                <el-button type="primary" @click="showBackgroundGallery = true">
                  {{ configForm.backgroundUrl ? '更换' : '选择' }}{{ configForm.backgroundType === 'image' ? '图片' : '视频' }}
                </el-button>
                <el-upload
                    :action="getUploadUrl()"
                    :headers="{ 'Authorization': 'Bearer ' + getToken() }"
                    :on-success="handleUploadSuccess"
                    :on-error="handleUploadError"
                    :before-upload="beforeBackgroundUpload"
                    :on-progress="handleUploadProgress"
                    :show-file-list="false"
                    :accept="configForm.backgroundType === 'image' ? 'image/jpeg,image/png' : 'video/mp4,video/webm'"
                    :data="{ fileType: configForm.backgroundType }"
                >
                  <el-button type="primary" :loading="isUploading">
                    {{ isUploading ? '上传中...' : '上传新' + (configForm.backgroundType === 'image' ? '图片' : '视频') }}
                  </el-button>
                </el-upload>
              </div>
            </div>
          </el-form-item>

          <!-- 背景适配方式 -->
          <el-form-item label="适配方式" prop="backgroundFit">
            <el-select v-model="configForm.backgroundFit" style="width: 120px">
              <el-option label="裁剪" value="crop"></el-option>
              <el-option label="覆盖" value="cover"></el-option>
              <el-option label="包含" value="contain"></el-option>
            </el-select>
          </el-form-item>

          <!-- 视频播放方式 -->
          <el-form-item v-if="configForm.backgroundType === 'video'" label="播放方式" prop="backgroundPlayStyle">
            <el-select v-model="configForm.backgroundPlayStyle" style="width: 120px">
              <el-option label="循环" value="loop"></el-option>
              <el-option label="单次" value="once"></el-option>
            </el-select>
          </el-form-item>
        </template>

        <el-form-item label="分辨率">
          <el-select v-model="configForm.resolution" placeholder="选择分辨率" label="分辨率" @change="handleResolutionChange" style="width: 120px">
<!--            <el-option label="1920x1080" value="1920x1080"></el-option>-->
            <el-option label="竖屏" value="1080x1920"></el-option>
            <el-option label="横屏" value="1280x720"></el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="是否开启字幕">
          <el-switch v-model="configForm.isCaption" />
        </el-form-item>

        <el-form-item label="设为默认">
          <el-switch v-model="configForm.isDefault" />
        </el-form-item>

      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="configDialog.visible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit" :loading="avatarStore.loading">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 音频播放器 -->
    <audio
        ref="audioPlayer"
        @ended="handleAudioEnd"
        style="display: none"
    ></audio>
  </div>

  <!-- 多数字人配置弹窗 -->
  <MultiAvatarConfigDialog
      v-model:visible="multiAvatarDialog.visible"
      :title="multiAvatarDialog.title"
      :default-config="defaultConfig"
      :submitting="submitting"
      @confirm="handleMultiAvatarConfirm"
  />

  <!-- 多数字人详情弹窗 -->
  <el-dialog
      v-model="multiAvatarDetailDialog.visible"
      title="多数字人配置详情"
      width="800px"
  >
    <div v-if="multiAvatarDetailDialog.config">
      <h3>配置名称：{{ multiAvatarDetailDialog.config.name }}</h3>

      <el-descriptions title="公共配置" :column="2" border>
        <el-descriptions-item label="背景类型">
          {{ getBackgroundTypeLabel(multiAvatarDetailDialog.config.commonConfig.backgroundType) }}
        </el-descriptions-item>
        <el-descriptions-item label="分辨率">
          {{ multiAvatarDetailDialog.config.commonConfig.width }} x {{ multiAvatarDetailDialog.config.commonConfig.height }}
        </el-descriptions-item>
        <el-descriptions-item label="是否开启字幕">
          {{ multiAvatarDetailDialog.config.isCaption ? '是' : '否' }}
        </el-descriptions-item>
      </el-descriptions>

      <div class="mt-4" style="margin-top: 16px">
        <el-descriptions title="数字人配置" :column="2" border>数字人配置</el-descriptions>
        <el-table :data="multiAvatarDetailDialog.avatars" border>
          <el-table-column label="序号" type="index" width="60" />
          <el-table-column label="数字人" min-width="180">
            <template #default="scope">
              <div class="avatar-cell">
                <el-image
                    :src="scope.row.avatar?.previewImageUrl"
                    class="avatar-preview"
                    fit="cover"
                >
                  <template #error>
                    <div class="image-placeholder">
                      <el-icon><Avatar /></el-icon>
                    </div>
                  </template>
                </el-image>
                <span>{{ scope.row.avatar?.avatarName }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="语音" min-width="150">
            <template #default="scope">
              <div class="voice-cell">
                <el-icon><Microphone /></el-icon>
                <span>{{ scope.row.voice?.name }}</span>
                <el-button
                    link
                    type="primary"
                    @click="handlePreviewVoice(scope.row.voice)"
                >试听</el-button>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="位置偏移" min-width="180">
            <template #default="scope">
              <div class="position-info">
                <div>X: {{ scope.row.xoffset }}</div>
                <div>Y: {{ scope.row.yoffset }}</div>
                <div>缩放: {{ scope.row.scale }}</div>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </el-dialog>

  <!-- 同步结果弹窗 -->
  <el-dialog
      v-model="syncDialog.visible"
      title="同步结果"
      width="600px"
  >
    <div class="sync-result">
      <div class="sync-status">
        <el-icon :class="syncDialog.success ? 'success' : 'error'">
          <CircleCheckFilled v-if="syncDialog.success" />
          <CircleCloseFilled v-else />
        </el-icon>
        <span>{{ syncDialog.message }}</span>
      </div>
      <div class="sync-details" v-if="syncDialog.details">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="新增角色">{{ syncDialog.details.added }}</el-descriptions-item>
          <el-descriptions-item label="更新角色">{{ syncDialog.details.updated }}</el-descriptions-item>
          <el-descriptions-item label="处理失败">{{ syncDialog.details.failed }}</el-descriptions-item>
        </el-descriptions>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="syncDialog.visible = false">关闭</el-button>
        <el-button type="primary" @click="handleRefreshAfterSync" v-if="syncDialog.success">
          刷新数据
        </el-button>
      </div>
    </template>
  </el-dialog>

  <el-dialog
      v-model="showBackgroundGallery"
      :title="configForm.backgroundType === 'image' ? '选择背景图片' : '选择背景视频'"
      width="900px"
      append-to-body
  >
    <BackgroundGallery
        :type="configForm.backgroundType"
        @select="handleBackgroundSelect"
    />
  </el-dialog>

  <!-- 虚拟人物选择弹窗 -->
  <el-dialog
      v-model="showAvatarDialog"
      title="选择虚拟人物"
      width="900px"
      append-to-body
  >
    <AvatarList @select="handleAvatarSelect" />
  </el-dialog>

  <!-- 语音选择弹窗 -->
  <el-dialog
      v-model="showVoiceDialog"
      title="选择语音"
      width="900px"
      append-to-body
  >
    <VoiceList @select="handleVoiceSelect" />
  </el-dialog>

  <!-- 人物预览弹窗 -->
  <el-dialog
      v-model="previewDialog.visible"
      title="虚拟人物预览"
      width="630"
      :close-on-click-modal="false"
  >
    <video
        width="600"
        v-if="previewDialog.videoUrl"
        :src="previewDialog.videoUrl"
        controls
        class="preview-video"
    ></video>
  </el-dialog>

  <!-- 视频预览弹窗 -->
  <el-dialog
      v-model="videoPreviewDialog.visible"
      title="视频预览"
      width="800px"
      destroy-on-close
      center
  >
    <div class="video-preview-container">
      <video
          v-if="videoPreviewDialog.url"
          :src="videoPreviewDialog.url"
          controls
          autoplay
          class="video-preview"
      ></video>
    </div>
  </el-dialog>
</template>

<script setup>
import {onMounted, reactive, ref, watch} from 'vue'
import {
  Avatar,
  CircleCheckFilled,
  CircleCloseFilled,
  Delete,
  Microphone,
  Plus,
  Refresh,
  RefreshRight,
  Search,
  VideoPlay
} from '@element-plus/icons-vue'
import {useConfigStore} from '@/stores/video/config'
import {useAvatarStore} from '@/stores/video/avatar'
import {useVoiceStore} from '@/stores/video/voice'
import { useBackgroundStore } from '@/stores/video/background'
import { getToken } from '@/utils/auth'
import { getUploadUrl } from '@/utils/uploadConfig';
import BackgroundGallery from "@/components/BackgroundGallery.vue";
import AvatarList from '@/components/AvatarSelect.vue'
import VoiceList from '@/components/VoiceSelect.vue'
import MultiAvatarConfigDialog from '@/components/MultiAvatarConfigDialog.vue'

import {ElMessage, ElMessageBox} from 'element-plus'
import {getGenderLabel, getGenderType, getLanguageLabel} from '@/utils/label'
import {formatDateTime} from "@/utils/date.js";

// Store
const configStore = useConfigStore()
const avatarStore = useAvatarStore()
const voiceStore = useVoiceStore()
const backgroundStore = useBackgroundStore()

const currentAvatar = ref(null);
const currentVoice = ref(null);
const showAvatarDialog = ref(false);
const showVoiceDialog = ref(false);
const previewDialog = reactive({
  visible: false,
  videoUrl: ''
});

const showBackgroundGallery = ref(false)

// 新增的响应式变量
const syncLoading = ref(false)
const lastSyncTime = ref(null)
const syncDialog = reactive({
  visible: false,
  success: false,
  message: '',
  details: null
})

const isUploading = ref(false)
const uploadProgress = ref(0)

// 监听背景库弹窗显示状态
watch(showBackgroundGallery, (value) => {
  if (value) {
    // 当弹窗打开时，重新获取背景库数据
    backgroundStore.getBackgrounds({
      page: 1,
      pageSize: 12,
      type: configForm.backgroundType
    })
  }
})

// 文件上传进度处理
const handleUploadProgress = (event) => {
  isUploading.value = true
  if (event.total > 0) {
    uploadProgress.value = Math.round((event.loaded / event.total) * 100)
  }
}

// 同步处理函数
const handleSync = async () => {
  syncLoading.value = true
  try {
    const result = await configStore.syncAvatars()
    syncDialog.success = true
    syncDialog.message = '同步成功'
    syncDialog.details = {
      added: result.added || 0,
      updated: result.updated || 0,
      failed: result.failed || 0
    }
    lastSyncTime.value = new Date()
  } catch (error) {
    syncDialog.success = false
    syncDialog.message = '同步失败：' + (error.message || '未知错误')
    syncDialog.details = null
  } finally {
    syncLoading.value = false
    syncDialog.visible = true
  }
}

// 同步后刷新数据
const handleRefreshAfterSync = async () => {
  syncDialog.visible = false
  await getList()
  await fetchAvatars()
}


// 搜索和筛选
const avatarSearch = ref('')
const avatarGenderFilter = ref('')
const avatarTypeFilter = ref('')
const voiceSearch = ref('')
const voiceLanguageFilter = ref('')
const voiceGenderFilter = ref('')
const selectedConfigs = ref([])

// 音频播放状态
const isPlaying = ref(false)

// 查询参数 - 添加配置类型筛选
const configsQuery = reactive({
  name: '',
  isDefault: null,
  configType: '', // 'single' 或 'multiple'
  pageNum: 1,
  pageSize: 10,
})

// 多数字人配置弹窗状态
const multiAvatarDialog = reactive({
  visible: false,
  title: '新增多数字人配置',
  config: null
})

// 多数字人配置详情弹窗
const multiAvatarDetailDialog = reactive({
  visible: false,
  config: null,
  avatars: []
})


// 提交状态
const submitting = ref(false)

// 分页查询参数
const avatarQuery = reactive({
  pageNum: 1,
  pageSize: 8,
  premium: null,
  name: '',
  gender: ''
})

const voiceQuery = reactive({
  pageNum: 1,
  pageSize: 10,
  name: '',
  language: '',
  gender: ''
})

// 表格选择
const handleSelectionChange = (selection) => {
  selectedConfigs.value = selection
}

// 处理分辨率变化
function handleResolutionChange(value) {
  const [width, height] = value.split('x').map(Number);
  configForm.width = width;  // 更新宽度
  configForm.height = height;  // 更新高度
}

// 监听搜索和筛选变化
watch([avatarSearch, avatarGenderFilter], ([newSearch, newGender]) => {
  avatarQuery.name = newSearch
  avatarQuery.gender = newGender
  avatarQuery.pageNum = 1
  fetchAvatars()
})

watch([avatarSearch, avatarTypeFilter], ([newSearch, newType]) => {
  avatarQuery.name = newSearch
  avatarQuery.premium = newType
  avatarQuery.pageNum = 1
  fetchAvatars()
})

watch([voiceSearch, voiceLanguageFilter], ([newSearch, newLanguage]) => {
  voiceQuery.name = newSearch
  voiceQuery.language = newLanguage
  voiceQuery.pageNum = 1
  fetchVoices()
})

watch([voiceSearch, voiceGenderFilter], ([newSearch, newGender]) => {
  voiceQuery.name = newSearch
  voiceQuery.gender = newGender
  voiceQuery.pageNum = 1
  fetchVoices()
})

// 获取数据
const fetchAvatars = () => {
  avatarStore.fetchAvatars(avatarQuery)
}

const fetchVoices = () => {
  voiceStore.fetchVoices(voiceQuery)
}

// 状态选项
const statusOptions = [
  { value: false, label: '用户配置' },
  { value: true, label: '默认配置' },
]

const voiceList = ref([])
const avatarList = ref([])

const setResolutionFromBackend = (row) => {
  const { width, height } = row;
  configForm.width = width;
  configForm.height = height;
  configForm.resolution = `${width}x${height}`;  // 将 width 和 height 组合成 resolution
}

// 获取文章列表
const getList = async () => {
  configStore.loading = true
  try {
    await configStore.fetchConfigs(configsQuery);


    // 从返回的数据中提取虚拟人物和语音列表
    const uniqueAvatars = new Map()
    const uniqueVoices = new Map()

    configStore.configs.forEach(config => {
      if (config.avatar) {
        uniqueAvatars.set(config.avatar.avatarId, config.avatar)
      }
      if (config.voice) {
        uniqueVoices.set(config.voice.voiceId, config.voice)
      }
    })

    avatarList.value = Array.from(uniqueAvatars.values())
    voiceList.value = Array.from(uniqueVoices.values())
  } catch (error) {
    console.error('Failed to fetch configs:', error)
  } finally {
    configStore.loading = false
  }
}

// 查询
const handleQuery = async () => {
  configsQuery.pageNum = 1
  await getList()
}

// 重置
const resetQuery = () => {
  configsQuery.name = ''
  configsQuery.width = 1280
  configsQuery.height = 720
  configsQuery.isDefault = null
  handleQuery()
}

// 分页方法
const handleSizeChange = (val) => {
  configsQuery.pageSize = val
  getList()
}

const handleCurrentChange = (val) => {
  configsQuery.pageNum = val
  getList()
}

// 表单
const configFormRef = ref(null)
const configDialog = reactive({
  visible: false,
  type: 'add'
})

const defaultConfig = ref(null)

const configForm = reactive({
  id: null,
  name: '',
  avatarId: '',
  voiceId: '',
  width: 1280,
  height: 720,
  // 人物配置 - 新增
  xOffset: 0.03,
  yOffset: 0.13,
  scale: 1.4,
  // 背景相关属性
  backgroundType: 'color',
  backgroundId: '',
  backgroundUrl: '',
  backgroundUrls: [],
  backgroundIds: [],
  backgroundColor: '#f6f6fc',
  backgroundFit: 'cover',
  backgroundPlayStyle: 'loop',
  resolution: '1280x720',
  isDefault: false,
  isCaption: false,
})

// 获取背景类型标签颜色
const getBackgroundTypeTag = (type) => {
  switch (type) {
    case 'color': return '';
    case 'image': return 'success';
    case 'video': return 'warning';
    default: return 'info';
  }
}

// 获取背景类型显示文字
const getBackgroundTypeLabel = (type) => {
  switch (type) {
    case 'color': return '颜色背景';
    case 'image': return '图片背景';
    case 'video': return '视频背景';
    default: return '未知类型';
  }
}

// 处理背景类型变化
const handleBackgroundTypeChange = (type) => {
  // 清空之前的背景设置
  if (type === 'color') {
    configForm.backgroundUrl = '';
    configForm.backgroundId = '';
    configForm.backgroundFit = 'crop';
    configForm.backgroundPlayStyle = 'loop';
  } else if (type === 'image' || type === 'video') {
    configForm.backgroundColor = '';
  }
}

// 移除已选背景
const removeBackground = () => {
  configForm.backgroundUrl = '';
  configForm.backgroundId = '';
}

// 视频鼠标交互
const handleVideoMouseOver = (event) => {
  event.target.play();
}

const handleVideoMouseOut = (event) => {
  event.target.pause();
  event.target.currentTime = 0;
}

// 背景上传相关
const beforeBackgroundUpload = (file) => {
  // 重置上传状态
  isUploading.value = true
  uploadProgress.value = 0

  const isImageType = file.type === 'image/jpeg' || file.type === 'image/png';
  const isVideoType = file.type === 'video/mp4' || file.type === 'video/webm';

  if (configForm.backgroundType === 'image' && !isImageType) {
    isUploading.value = false
    ElMessage.error('背景图片只能是 JPG 或 PNG 格式!');
    return false;
  }

  if (configForm.backgroundType === 'video' && !isVideoType) {
    isUploading.value = false
    ElMessage.error('背景视频只能是 MP4 或 WEBM 格式!');
    return false;
  }

  const maxSize = 50 * 1024 * 1024; // 50MB
  if (file.size > maxSize) {
    isUploading.value = false
    ElMessage.error('文件大小不能超过 50MB!');
    return false;
  }

  return true;
}

const handleUploadSuccess = (response) => {
  isUploading.value = false
  uploadProgress.value = 100

  if (response.code === 200 && response.data) {
    configForm.backgroundUrl = response.data.url;
    configForm.backgroundId = response.data.id;
    ElMessage.success('上传成功');

    // 刷新背景资源库数据
    backgroundStore.getBackgrounds({
      page: 1,
      pageSize: 12,
      type: configForm.backgroundType
    });
  } else {
    ElMessage.error(response.message || '上传失败');
  }
}

const handleUploadError = (error) => {
  isUploading.value = false
  uploadProgress.value = 0
  ElMessage.error('上传失败，请稍后重试');
}

// 处理背景选择
const handleBackgroundSelect = (background) => {
  configForm.backgroundUrl = background.url;
  configForm.backgroundId = background.id;
  showBackgroundGallery.value = false;
}


const rules = {
  name: [
    { required: true, message: '请输入配置名称', trigger: 'blur' },
    { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
  ],
  avatarId: [
    { required: true, message: '请选择虚拟人物', trigger: 'change' }
  ],
  voiceId: [
    { required: true, message: '请选择语音', trigger: 'change' }
  ]
}

// 音频播放
const audioPlayer = ref(null)
const currentAudioUrl = ref('')

// 修改添加配置方法，区分单数字人和多数字人模式
const handleAdd = (mode) => {
  if (mode === 'multiple') {
    // 打开多数字人配置弹窗
    multiAvatarDialog.title = '新增多数字人配置'
    multiAvatarDialog.config = null
    multiAvatarDialog.visible = true
  } else {
    // 原有的单数字人配置添加逻辑
    configDialog.type = 'add'
    configDialog.visible = true
    resetForm()
  }
}

// 修改编辑方法，区分单数字人和多数字人模式
const handleEdit = async (row) => {
  if (row.configType === 'multiple') {
    // 编辑多数字人配置
    try {
      // 加载多数字人配置详情
      const configDetail = await configStore.getMultiAvatarConfig(row.id)

      multiAvatarDialog.title = '编辑多数字人配置'
      multiAvatarDialog.config = configDetail
      multiAvatarDialog.visible = true
      defaultConfig.value = multiAvatarDialog.config

    } catch (error) {
      console.error('加载多数字人配置失败:', error)
      ElMessage.error('加载配置失败')
    }
  } else {
    // 原有的单数字人配置编辑逻辑
    configDialog.type = 'edit'
    configDialog.visible = true

    Object.assign(configForm, row)
    setResolutionFromBackend(row)

    // 单独获取人物详细信息
    if (row.avatarId) {
      try {
        await avatarStore.fetchById(row.avatarId);
        currentAvatar.value = avatarStore.avatar;
      } catch (error) {
        console.error('获取人物信息失败:', error);
        ElMessage.warning('无法加载选中的人物信息');
      }
    } else {
      currentAvatar.value = null;
    }

    // 单独获取语音详细信息
    if (row.voiceId) {
      try {
        await voiceStore.fetchVoiceById(row.voiceId);
        currentVoice.value = voiceStore.voice;
      } catch (error) {
        console.error('获取语音信息失败:', error);
        ElMessage.warning('无法加载选中的语音信息');
      }
    } else {
      currentVoice.value = null;
    }
  }
}

// 处理多数字人配置提交
const handleMultiAvatarConfirm = async (config) => {
  try {
    submitting.value = true

    // 构建请求参数
    let params
    if (config.mode === 'multiple') {
      params = {
        id: multiAvatarDialog.config?.id,
        name: config.name,
        configType: 'multiple',
        commonConfig: config.commonConfig,
        avatarConfigs: config.avatarConfigs
      }
      // 保存配置
      await configStore.saveMultiAvatarConfig(params)
    } else {
      // 兼容单数字人模式
      params = {
        id: multiAvatarDialog.config?.id,
        name: config.config.name,
        configType: 'single',
        ...config.config
      }
      // 保存配置
      await configStore.saveVideoConfig(params)
    }

    // 关闭弹窗并刷新列表
    multiAvatarDialog.visible = false
    await getList()

    ElMessage.success(`${multiAvatarDialog.config ? '更新' : '新增'}配置成功`)
  } catch (error) {
  } finally {
    submitting.value = false
  }
}

// 查看多数字人配置详情
const viewMultiAvatars = async (config) => {
  try {
    // 加载多数字人配置详情
    const configDetail = await configStore.getMultiAvatarConfig(config.id)

    multiAvatarDetailDialog.config = configDetail
    multiAvatarDetailDialog.avatars = await Promise.all(
        (configDetail.avatarConfigs || []).map(async (avatarConfig) => {
          // 加载每个数字人和语音的详细信息
          let avatar = null
          let voice = null

          try {
            if (avatarConfig.avatarId) {
              await avatarStore.fetchById(avatarConfig.avatarId)
              avatar = avatarStore.avatar
            }
          } catch (error) {
            console.error('加载数字人信息失败:', error)
          }

          try {
            if (avatarConfig.voiceId) {
              await voiceStore.fetchVoiceById(avatarConfig.voiceId)
              voice = voiceStore.voice
            }
          } catch (error) {
            console.error('加载语音信息失败:', error)
          }

          return {
            ...avatarConfig,
            avatar,
            voice
          }
        })
    )

    multiAvatarDetailDialog.visible = true
  } catch (error) {
    console.error('加载多数字人配置详情失败:', error)
    ElMessage.error('加载配置详情失败')
  }
}

// 添加虚拟人物选择处理方法
const handleAvatarSelect = (avatar) => {
  currentAvatar.value = avatar;
  configForm.avatarId = avatar.avatarId;
  showAvatarDialog.value = false;
};

// 添加语音选择处理方法
const handleVoiceSelect = (voice) => {
  currentVoice.value = voice;
  configForm.voiceId = voice.voiceId;
  showVoiceDialog.value = false;
};

// 添加视频预览相关的变量
const videoPreviewDialog = reactive({
  visible: false,
  url: ''
});

// 预览视频
const previewVideo = (url) => {
  if (!url) {
    ElMessage.warning('无效的视频链接');
    return;
  }
  videoPreviewDialog.url = url;
  videoPreviewDialog.visible = true;
};

// 新增方法：处理试听所选语音
const handlePreviewVoice = (voice) => {
  if (!voice?.previewAudio) {
    ElMessage.warning('暂无试听音频');
    return;
  }

  // 如果当前正在播放，则停止播放
  if (isPlaying.value) {
    stopAudio();
    return;
  }

  // 验证音频URL
  if (!isValidAudioUrl(voice.previewAudio)) {
    ElMessage.error('无效的音频文件地址');
    return;
  }

  try {
    // 设置音频源并播放
    audioPlayer.value.src = voice.previewAudio;
    audioPlayer.value.play().then(() => {
      isPlaying.value = true;
    });
  } catch (err) {
    console.error('音频播放失败:', err);
  }
};

// 增强删除方法，区分单数字人和多数字人模式
const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm('确认删除该配置吗？', '提示', {
      type: 'warning'
    })

    if (row.configType === 'multiple') {
      await configStore.removeMultiAvatarConfig(row.id)
    } else {
      await configStore.removeConfig(row.id)
    }

    await getList()
  } catch {
    // 用户取消删除
  }
}

const handleBatchDelete = async () => {
  if (selectedConfigs.value.length === 0) {
    ElMessage.warning('请选择要删除的配置')
    return
  }

  await ElMessageBox.confirm(`确认删除 ${selectedConfigs.value.length} 个配置吗？`, '提示', {
    type: 'warning',
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  }).then(async () => {
    await a
  }).catch(async () => {
    const ids = selectedConfigs.value.map(item => item.id)
    await configStore.batchDelete(ids)
    await getList()
  })
}

const handleSetDefault = async (row, value) => {
  if (value) {
    await configStore.setDefault(row.id)
  }
}

const handleSetCaption = async (row, value) => {
  if (value) {
    await configStore.setCaption(row.id)
  }
}

// 停止音频播放
const stopAudio = () => {
  if (audioPlayer.value) {
    audioPlayer.value.pause()
    audioPlayer.value.src = '' // 清除音频源
    isPlaying.value = false
  }
}

// 验证音频URL是否有效
const isValidAudioUrl = (url) => {
  if (!url) return false

  try {
    new URL(url)
    return true
  } catch (e) {
    console.error('Invalid audio URL:', e)
    return false
  }
}

const handleAudioEnd = () => {
  currentAudioUrl.value = ''
}

const handleSubmit = async () => {
  if (!configFormRef.value) return

  try {
    await configFormRef.value.validate()

    const formData = {
      ...configForm,
      // 确保背景相关属性被正确提交
      backgroundType: configForm.backgroundType,
      backgroundId: configForm.backgroundId,
      backgroundUrl: configForm.backgroundType !== 'color' ? configForm.backgroundUrl : '',
      backgroundUrls: configForm.backgroundUrls || [],
      backgroundIds: configForm.backgroundIds || [],
      backgroundColor: configForm.backgroundType === 'color' ? configForm.backgroundColor : '',
      backgroundFit: configForm.backgroundType !== 'color' ? configForm.backgroundFit : '',
      backgroundPlayStyle: configForm.backgroundType === 'video' ? configForm.backgroundPlayStyle : ''
    };

    await configStore.saveVideoConfig(formData);

    configDialog.visible = false;
    await getList();
    ElMessage.success(`${configDialog.type === 'add' ? '新增' : '更新'}配置成功`);
  } catch {
    // 错误已在store中处理
  }
}

const resetForm = () => {
  if (configFormRef.value) {
    configFormRef.value.resetFields()
  }
  Object.assign(configForm, {
    id: null,
    name: '',
    avatarId: '',
    voiceId: '',
    // 人物配置 - 新增
    xOffset: 0.03,
    yOffset: 0.13,
    scale: 1.4,
    backgroundColor: '#f6f6fc',
    backgroundType: 'color',
    backgroundId: '',
    backgroundUrl: '',
    backgroundUrls: [],
    backgroundIds: [],
    backgroundFit: 'cover',
    backgroundPlayStyle: 'loop',
    width: 1080,
    height: 1920,
    isDefault: false
  })
  currentAvatar.value = null;
  currentVoice.value = null;
}

const getLastSync = async () => {
  try {
    lastSyncTime.value = await configStore.getLastSyncInfo()
  } catch (error) {
    console.error('Failed to get last sync time:', error)
  }
}

// 初始化
onMounted(async () => {
  await Promise.all([
    getList(),
    fetchAvatars(),
    fetchVoices(),
    getLastSync()
  ])
})
</script>

<style scoped>
/* 背景缩略图样式优化 */
.background-thumbnail {
  width: 80px;
  height: 45px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid #e0e0e0;
}

.video-container {
  position: relative;
  cursor: pointer;
}

.video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.1);
  border-radius: 4px;
}

.video-icon {
  color: #fff;
  font-size: 20px;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  padding: 5px;
}

.video-preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.video-preview {
  max-width: 100%;
  max-height: 70vh;
  border-radius: 4px;
}

.background-resource-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
}


.remove-btn {
  position: absolute;
  top: 5px;
  left: 1px;
}

.background-actions {
  display: flex;
  gap: 10px;
}

.preview-content {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 4px;
}

.preview-image {
  width: 60px;
  height: 60px;
  border-radius: 4px;
  margin-right: 10px;
}

.preview-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.select-preview {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.preview-tags {
  display: flex;
  gap: 5px;
}

.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
}

.select-preview {
  display: flex;
  align-items: center;
  gap: 16px;
}

.preview-content {
  flex: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 16px;
  background: var(--el-fill-color-light);
  border-radius: 4px;
}

.preview-image {
  width: 40px;
  height: 40px;
  border-radius: 4px;
}

.preview-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.preview-tags {
  display: flex;
  gap: 4px;
}

.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background: var(--el-fill-color-darker);
  color: var(--el-text-color-secondary);
}

.dialog-footer {
  padding-top: 20px;
  text-align: right;
}

.preview-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.select-preview {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.preview-content {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 4px;
}

/* 背景资源容器样式 */
.background-resource-container {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.preview-image,
.preview-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


.background-actions {
  display: flex;
  gap: 10px;
}

/* 背景缩略图样式 */
.background-thumbnail {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid #e0e0e0;
}

.video-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 20px;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  padding: 5px;
}

/* 颜色值显示 */
.color-value {
  margin-left: 10px;
}

/* 颜色样式 */
.color-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.color-block {
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
}

/* 图片占位符样式 */
.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  color: #909399;
  font-size: 24px;
}

.sync-result {
  padding: 20px;
}

.sync-status {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}

.sync-status .el-icon {
  font-size: 24px;
  margin-right: 10px;
}

.sync-status .success {
  color: var(--el-color-success);
}

.sync-status .error {
  color: var(--el-color-danger);
}

.sync-details {
  margin-top: 20px;
}

.select-item:hover .select-item-content {
  border-color: #409EFF;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.select-item.active .select-item-content {
  border-color: #409EFF;
  box-shadow: 0 0 0 1px #409EFF;
}

.image-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #f5f7fa;
  color: #909399;
  font-size: 24px;
}

.select-item:hover .select-item-content {
  border-color: #409EFF;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.select-item.active .select-item-content {
  border-color: #409EFF;
  box-shadow: 0 0 0 1px #409EFF;
}

.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
  font-size: 24px;
}

:deep(.el-table .el-radio) {
  margin-right: 0;
}

.dialog-footer {
  padding-top: 20px;
  text-align: right;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.config-container {
  padding: 20px;
}

.avatar-cell,
.voice-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.avatar-preview {
  width: 40px;
  height: 40px;
  border-radius: 4px;
}

.color-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.color-block {
  width: 20px;
  height: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 2px;
}

.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
  font-size: 24px;
}

.dialog-footer {
  padding-top: 20px;
  text-align: right;
}

:deep(.el-table .el-radio) {
  margin-right: 0;
}

</style>